﻿using AutoMapper;
using ProjectManageSystemApi.DbEntity;
using ProjectManageSystemApi.Enums;
using ProjectManageSystemApi.Models;
using ProjectManageSystemApi.Models.ProjectUserInfo;
using ProjectManageSystemApi.Utilities;
using System;
using System.Collections.Generic;
using System.Linq;

namespace ProjectManageSystemApi.Services.Impl
{
    public class ProjectUserInfoServices : IProjectUserInfoServices
    {
        readonly IFreeSql _fsql;
        readonly IMapper _mapper;
        public ProjectUserInfoServices(IFreeSql fsql, IMapper mapper)
        {
            this._fsql = fsql;
            this._mapper = mapper;
        }

        public bool Insert(ProjectUserIdsDto projectUser, long createUser)
        {
            try
            {
                _fsql.Transaction(() =>
                {
                    var datas = _fsql.Select<UserInfo>()
                        .LeftJoin(x => x.ProjectUserInfo.UserId == x.Id
                            && x.ProjectUserInfo.ProjectId == projectUser.ProjectId)
                        .Where(x => projectUser.UserId.Contains(x.Id))
                        .ToList(x => new ProjectUserInfoSql
                        {
                            Id = x.ProjectUserInfo.Id,
                            ProjectId = projectUser.ProjectId,
                            UserId = x.Id,
                            CreateUser = createUser,
                            CreateTime = DateTime.Now.GetMillUtcTimeStamp(),
                            Status = (byte)ProjectUserInfoStatus.Default,
                            HasExist = x.ProjectUserInfo != null
                        });
                    if (datas.Count == 0)
                    {
                        throw new DbTranException("没有增加数据");
                    }

                    var insertData = _mapper.Map<List<ProjectUserInfo>>(datas.Where(x => !x.HasExist));
                    bool r = _fsql.Insert(insertData).ExecuteAffrows() >= insertData.Count;
                    if (!r)
                    {
                        throw new DbTranException("增加失败");
                    }

                    var updateData = _mapper.Map<List<ProjectUserInfo>>(datas.Where(x => x.HasExist));
                    var row = _fsql.Update<ProjectUserInfo>().SetSource(updateData)
                        .UpdateColumns(x => x.Status).ExecuteAffrows();
                    r = row >= updateData.Count;
                    if (!r)
                    {
                        throw new DbTranException("修改失败");
                    }
                });
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }

        public bool Insert(ProjectUserIdDto projectUser, long createUser) 
        {
            var data = _mapper.Map<ProjectUserInfo>(projectUser);
            data.CreateUser = createUser;
            data.CreateTime = DateTime.Now.GetMillUtcTimeStamp();
            data.Status = (byte)ProjectUserInfoStatus.Default;
            return _fsql.Insert(data).ExecuteAffrows() > 0;
        }

        public bool Delete(ProjectUserIdDto projectUser)
        {
            return _fsql.Update<DbEntity.ProjectUserInfo>()
                .Set(x => x.Status, (byte)ProjectUserInfoStatus.Delete)
                .Where(x => x.UserId == projectUser.UserId && x.ProjectId == projectUser.ProjectId)
                .ExecuteAffrows() > 0;
        }

        /// <summary>
        /// 查询当前项目成员
        /// </summary>
        /// <param name="pageBo"></param>
        /// <returns></returns>
        public Models.PageVo<List<ProjectUserInfoDto>> Query(Models.PageBo<ProjectUserInfoParams> pageBo)
        {
            var data = _fsql.Select<ProjectUserInfo>().Where(x => x.ProjectId == pageBo.Param.ProjectId)
                .Include(x => x.User)
                .IncludeMany(x => x.User.UserRoleLink)
                .IncludeMany(x => x.User.UserRoleLink, then =>
                {
                    then.Include(y => y.Role);
                })
                .Where(x => x.Status < (byte)ProjectUserInfoStatus.Delete);
            if (!string.IsNullOrWhiteSpace(pageBo.Param.UserName))
            {
                data = data.Where(x => x.User.UserName.Contains(pageBo.Param.UserName));
            }
            long count = data.Count();
            data = data.Page(pageBo.Page, pageBo.Size);
            return new Models.PageVo<List<ProjectUserInfoDto>>
            {
                Page = pageBo.Page,
                Size = pageBo.Size,
                Total = count,
                Datas = _mapper.Map<List<ProjectUserInfoDto>>(data.ToList())
            };
        }

        /// <summary>
        /// 获取项目外的人
        /// </summary>
        public IEnumerable<UserRoleDto> GetUserOutsizeProject(int projectId)
        {
            var datas = _fsql.Select<UserInfo>()
                .Where(x=> !_fsql.Select<ProjectUserInfo>().Where(p => p.ProjectId == projectId)
                    .Any(e => e.UserId == x.Id && e.Status < (byte)ProjectUserInfoStatus.Delete))
                .IncludeMany(x => x.UserRoleLink)
                .IncludeMany(x => x.UserRoleLink, then =>
                {
                    then.Include(y => y.Role);
                });
            return _mapper.Map<List<UserRoleDto>>(datas.ToList());
        }

        public bool HasExist(ProjectUserIdDto project) 
        {
            return _fsql.Select<ProjectUserInfo>()
                .Any(x => x.ProjectId == project.ProjectId && x.UserId == project.UserId && x.Status < (byte)ProjectUserInfoStatus.Delete);        
        }

        /// <summary>
        /// 获取所有的人，包括删除的
        /// </summary>
        /// <returns></returns>
        public List<ProjectUserInfoDto> GetAll(int projectId)
        {
            var data = _fsql.Select<ProjectUserInfo>().Where(x => x.ProjectId == projectId)
                .Include(x => x.User)
                .IncludeMany(x => x.User.UserRoleLink)
                .IncludeMany(x => x.User.UserRoleLink, then =>
                {
                    then.Include(y => y.Role);
                })
                .OrderBy(x => x.Status);
            return _mapper.Map<List<ProjectUserInfoDto>>(data.ToList());
        }
    }
}
